import React, {
  createContext,
  Dispatch,
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import { TextWidget, getMessage } from '@inbiz/react';
import { useForm } from '@formily/react';
import { Field } from '@formily/core';
import { Button, message, Modal, Tabs, Tooltip } from 'antd';
import cls from 'classnames';
import AuthForm, { useAuth } from '@inbiz/basic/AuthForm';
import { getPageTree, tileTree } from '@inbiz/setters';
import EditableTable, { IColumns } from '@inbiz/basic/EditableTable';
import { getPlatform, InbizIcon, uuid } from '@inbiz/utils';
import tableApi from '../../preview/web/serviceApi';
import { useQueryFields } from '@inbiz/hooks';
import { ColumnType } from 'rc-table/lib/interface';
import { ExclamationCircleOutlined } from '@ant-design/icons';
import {
  ActionEnum,
  actionHeader,
  Actions,
  arrIsEmpty,
  ConfigHeader,
  InputTypeEnum,
  getPropHeader,
  TabsConfig,
  TmplDefaultConfig,
} from '../../shared';
import { isFunction } from 'lodash';
import FieldForm from './FieldForm';
import { ActionConfigType, RecordType } from '../../interfaces';
import { TmplType } from './CardTmplSelect';
import { useFormatCardAttrColumns } from '../../hooks';
import '../../style.less';


export interface ConfigColumn extends ColumnType<RecordType> {
  field?: string;
  alias?: string;
  visible?: boolean;
  searchable?: boolean;
  inputType?: InputTypeEnum;
}

interface ColumnConfigProps {
  onChange: (value: any) => void;
  prefixCls?: string;
  value: { [key: string]: any };
  thumbnail: boolean;
}

type EditableType = {
  editData?: any;
  dataIndex: string;
  render?: (value: string) => string;
};
type TmplInfoType = { tmplList: TmplType[]; selected: string };

interface TmplCtxProps {
  setTmplInfo: Dispatch<any>;
  onSaveCardTmpl?: Dispatch<any>;
  tmplInfo: TmplInfoType;
}

export const TmplCtx = createContext<TmplCtxProps>({
  setTmplInfo: () => { },
  tmplInfo: { tmplList: [], selected: 'default' },
});

const ColumnConfig: React.FC<ColumnConfigProps> = (props) => {
  const { prefixCls = 'inbiz-config-modal', value, thumbnail } = props;
  const [pages, setPages] = useState();
  const [visible, setVisible] = useState(false);
  const [activeKey, setActiveKey] = useState('actions');
  const [expandedRowKeys, setExpandedRowKeys] = useState<string[]>([]);
  const [tmplInfo, setTmplInfo] = useState<TmplCtxProps['tmplInfo']>({
    tmplList: value?.formItems?.tmplList || [
      {
        name: '默认模板',
        id: 'default',
        config: TmplDefaultConfig,
      },
    ],
    selected: value?.formItems?.cardTmpl?.id || 'default',
  });
  const form = useForm();
  const formItemsRef = useRef({ formItems: value?.formItems });
  const [choosedAuth, changeHandle, generateFlag] = useAuth();
  const viewType = thumbnail
    ? 'card'
    : (form.query('*.tableViewType')?.take?.() as Field)?.value || 'table';
  const resizeField = (form.query(/resizeColumnWidth$/)?.take?.() as Field)?.value || false;
  const sourceType = (form.query(/sourcetype$/).take() as Field)?.value;
  const modelKey = visible
    ? (form.fields?.['form.senior.soure.x-component-props.sourceModel'] as unknown as Field)?.value
    : undefined;
  const authOption = useMemo(() => {
    return (choosedAuth?.allInfo?.Children || []).map((ele) => ({
      value: ele.ObjectValue,
      label: ele.ObjectValue + `(${getMessage(ele.ObjectName)})`,
    }));
  }, [choosedAuth]);
  const refObj = useMemo(() => {
    return Object.keys(TabsConfig(form)).reduce((refObjs, key) => {
      refObjs[key] = React.createRef<EditableTable>();
      return refObjs;
    }, {});
  }, [value.tableValues]);
  const [fields, loading] = useQueryFields(
    {
      key: modelKey,
      appId: form['appInfo']!.appId,
    },
    [modelKey],
  );
  const newFields = useMemo(() => {
    return fields.filter((field) => !field.IsMany);
  }, [fields]);
  const addHandler = {
    attrs: () => {
      return { id: uuid(5, 5), width: 100, visible: '1' };
    },
  };
  /**
   * 验证操作类型是否有重复(除自定义操作)
   * @param actions 操作按钮组
   */
  const validateActionUnique = (actions: ActionConfigType[]) => {
    actions.reduce((groups: any, cur: ActionConfigType) => {
      if (groups[cur.actionType]) {
        const typeName = Actions().find((action) => action.value === cur.actionType)?.label;
        throw new Error(
          `${getMessage('table.operatingType')}${getMessage(
            typeName || cur.actionName,
          )}${getMessage('table.repeat')}`,
        );
      }
      if (cur.actionType === ActionEnum.custom) {
        return groups;
      }
      groups[cur.actionType] = cur;
      return groups;
    }, {});
  };
  // 格式化操作
  const formatActions = useCallback(() => {
    if (loading) {
      return;
    }
    const newHeader =
      viewType === 'table'
        ? actionHeader(authOption).filter((col) => col && col.dataIndex !== 'auth')
        : [...actionHeader(authOption)].filter((col) => col);
    for (const col of newHeader) {
      if ((col as EditableType)?.dataIndex === 'page') {
        (col as EditableType).editData.options = pages;
      }
    }
    return newHeader;
  }, [pages, viewType, authOption]);
  // 格式化属性
  const formatAttrs = useCallback(() => {
    if (loading || arrIsEmpty(newFields)) {
      return;
    }
    const PropHeader = getPropHeader(form);
    const newHeader = viewType === 'table' ? [...PropHeader] : ConfigHeader(form);
    const sourceType = (form.query(/sourcetype$/)?.take() as Field)?.value;
    const newGroups = fields.reduce((groups: any, field) => {
      const [modelName, attrName] = field.origin_FieldName?.split('$') || [];
      if (!field.Master) {
        field.label = attrName;
      }
      if (groups[field.ModelKey]) {
        groups[field.ModelKey].options.push(field);
      } else {
        groups[field.ModelKey] = {
          ...field,
          label: modelName || field?.value,
          key: field.ModelKey,
          options: field.IsMany && !field.Master ? field.childList :[field],
        };
      }
      return groups;
    }, {});
    for (const col of newHeader) {
      if ((col as EditableType).dataIndex === 'propName') {
        if (sourceType === 'api') {
          (col as EditableType).editData.options = newFields;
        }
        (col as EditableType).editData.optgroups = Object.keys(newGroups).map(
          (key) => newGroups[key],
        );
        (col as EditableType).render = (val: string) => {
          return val?.includes('$') ? val.replace('$', '.') : val;
        };
        (col as EditableType).editData.afterEdit = (index, record) => {
          if (record.propName?.includes('$')) {
            const [ modelName ] = record.propName.split('$')
            const currentModel = fields.find(field => field?.value === modelName);
            const columnName = currentModel?.childList?.find(ele => ele.value == record.propName)?.columnName
            return {
              ...record,
              columnName
            }
          }
          const columnName = newFields?.find(ele => ele.value == record.propName)?.columnName
          return {
            ...record,
            columnName
          }
        }
        break;
      }
    }
    return newHeader;
  }, [newFields, loading, viewType, form]);
  const processor = {
    actions: formatActions,
    attrs: formatAttrs,
  };
  // 初始化表格卡片属性
  const initCardAttrs = (tmplInfoParam: TmplCtxProps['tmplInfo'], id?: string) => {
    const selectedTmpl = tmplInfoParam?.tmplList.find((tmpl: TmplType) => tmpl.id === id);
    let newAttrs: any[] = [];
    if (selectedTmpl) {
      const { config = TmplDefaultConfig } = selectedTmpl;
      Object.keys(config)?.forEach((key) => {
        if (config[key]?.children && config[key]?.children.length) {
          config[key].children = config[key]?.children.map((item) => {
            item['id'] = uuid(5, 5);
            return item;
          });
        }
        newAttrs.push({ ...config[key], id: uuid(5, 5) });
      });
    }
    if (value.tableValues) {
      value.tableValues.attrs = newAttrs;
    }
  };
  // 初始化表格列表属性
  const initTableAttrs = async () => {
    const modelKey = value?.queryFields?.find((field) => field?.Master)?.ModelKey;
    let manyFields = [];
    // 获取该模型下的字段类型，用于配置时，后端的长文本字段不能配置排序
    if (modelKey) {
      manyFields = await tableApi.getManyFields(form['appInfo']!.appId, modelKey);
    }
    const _fields = manyFields?.[0]?.Fields || [];
    if (fields && fields.length > 0) {
      // 新拖入的表格组件，添加属性对应的类型
      if (!value.tableValues?.attrs) {
        const newAttrs = fields.map((field) => {
          const fieldType = _fields.find(item => item.Name == field.value)?.Type;
          return {
            propName: field.value,
            visible: '1',
            width: 100,
            id: uuid(5, 5),
            fieldType: fieldType
          }
        });
        if (value.tableValues) {
          value.tableValues.attrs = newAttrs;
        }
      } else {
        // 兼容表格老数据，添加属性对应的类型
        value.tableValues.attrs.forEach(attr => {
          const fieldType = _fields.find(item => item.Name == attr.propName)?.Type;
          attr['fieldType'] = fieldType;
        })
      }
    }
    // 移动化表格查询字段默认赋值
    if (getPlatform() == 'wap') {
      const optgroups = processor
        .attrs()
        ?.filter((item) => item.dataIndex == 'propName')?.[0]
        .editData.optgroups.map((item) => {
          return {
            ...item,
            value: item.origin_FieldName,
          };
        });
      value.formItems.searchFiled = value.formItems.searchFiled
        ? value.formItems.searchFiled
        : optgroups?.[0].value;
    }
  };
  // 保存配置
  const setData = useCallback(async () => {
    const promises = [];
    let flagList = [];
    for (const key of Object.keys(refObj)) {
      if (!refObj[key].current) {
        //没有点开其他tab
        promises.push(
          new Promise((resolve) => {
            resolve({ [key]: value?.tableValues?.[key] });
          }),
        );
        continue;
      }
      promises.push(
        new Promise((resolve, reject) => {
          refObj[key].current
            .getData()
            .then((res: any) => {
              if (key === 'actions') {
                flagList = res.map((ele) => ({ value: ele.operationflag, label: ele.actionName }));
              }
              resolve({ [key]: res });
            })
            .catch((err: any) => {
              setActiveKey(key);
              reject(err);
            });
        }),
      );
    }

    Promise.all(promises)
      .then((values) => {
        let tableValues: { actions?: ActionConfigType[] } = {};
        for (const data of values) {
          tableValues = {
            ...tableValues,
            ...(data as any),
          };
        }
        if (tableValues.actions) {
          try {
            validateActionUnique(tableValues.actions);
          } catch (e: any) {
            message.error(e.message);
            return;
          }
        }
        setVisible(false);
        generateFlag(flagList).then(() => {
          props.onChange({
            tableValues,
            queryFields: newFields?.map((field) => {
              const [modelName] = field.origin_FieldName?.split('$') || [];
              return {
                ...field,
                label: !field.Master ? `${modelName}.${field.label}` : field.label,
              };
            }),
            formItems: {
              ...value?.formItems,
              ...formItemsRef.current.formItems,
              ...tmplInfo,
            },
            auth: choosedAuth?.value,
          });
        });
      })
      .catch((err) => {
        console.log('config-err>>>', err);
      });
  }, [newFields, value, tmplInfo, choosedAuth]);
  // 保存卡片模板
  const onSaveCardTmpl = useCallback(
    (id) => {
      setTmplInfo((pre: TmplInfoType) => {
        if (pre.selected === id) {
          return pre;
        }
        initCardAttrs(tmplInfo, id);
        return {
          ...pre,
          selected: id,
        };
      });
    },
    [tmplInfo, value],
  );
  // 添加数据项
  const handleAdd = useCallback(() => {
    return { id: uuid(5, 5) };
  }, []);
  // 设置选中行
  const setExpandedRowKey = (value: any) => {
    setExpandedRowKeys([value]);
  };
  // 表格是否可添加子表格
  const expandable = useCallback(
    (viewType: string, key: string) => {
      if (viewType === 'card' && key === 'attrs') {
        return {
          expandIcon: ({ expanded, onExpand, record }: any) => {
            if (record?.typeValue === 'array') {
              return expanded ? (
                <span
                  onClick={(e) => {
                    setExpandedRowKeys([]);
                  }}
                  title={getMessage('table.button.putAway')}
                  className="inbiz-card-attrs-expanded"
                >
                  <InbizIcon type="icon-ic-arrow-down-bold" />
                </span>
              ) : (
                <span
                  onClick={(e) => {
                    setExpandedRowKeys([record?.id]);
                  }}
                  title={getMessage('table.button.expand')}
                  className="inbiz-card-attrs-expanded"
                >
                  <InbizIcon type="icon-ic-arrow-right-bold" />
                </span>
              );
            }
            return undefined;
          },
          expandedRowKeys: expandedRowKeys,
        };
      }
      return undefined;
    },
    [value.tableValues?.attrs, expandedRowKeys],
  );
  // 表格配置渲染前验证
  const validateRender = (key: string) => {
    const config = TabsConfig()[key][viewType];
    const header = processor[key]?.() || config.header;
    let newValue = value?.formItems || {};
    // H5格式化查询属性option
    if (config.name == '属性' && viewType == 'table' && getPlatform() == 'wap') {
      config.formItems = config.formItems.map((item: any) => {
        if (item.name == 'searchFiled') {
          if (newFields.length) {
              const options = header
              .filter((item2: any) => item2.dataIndex == 'propName')?.[0]
              .editData.optgroups?.map((item3: any) => {
                return {
                  ...item3,
                  options: item3.options?.map((item4: any) => {
                    return {
                      ...item4,
                      value: item4.origin_FieldName,
                    };
                  }),
                };
              });
            formItemsRef.current.formItems = {
              ...formItemsRef.current.formItems,
              searchFiled: formItemsRef.current.formItems?.searchFiled
                ? formItemsRef.current.formItems.searchFiled
                : newFields[0].origin_FieldName,
            };
            return {
              ...item,
              options: options,
            };
          } else {
            return {...item, inputType: 1}
          }
        } else {
          return item;
        }
      });
    }
    const add = addHandler[key] || handleAdd;
    let columns = isFunction(header) ? header(authOption) : (header as IColumns) ?? [];
    columns = columns.filter((col: { [key: string]: any }) => col);
    columns?.map((item:any)=>{
      if(item.dataIndex=="buttonColor"){
        item.title= (
          <span>
            <span style={{ paddingRight: '10px' }}><TextWidget>Table.buttonColor</TextWidget></span>
            <Tooltip title={getMessage('Table.tips.operationflag')}>
              <ExclamationCircleOutlined />
            </Tooltip>
          </span>
        ),
        item.render= (val, row, index) => {
          return (
            <div style={{ display: 'flex' }} title={val}>
              <div
                style={{ minWidth: 20, height: 20, backgroundColor: val }}
              ></div>
              <div
                style={{
                  lineHeight: '20px',
                  width: 120,
                  overflow: 'hidden',
                  whiteSpace: 'nowrap',
                  textOverflow: 'ellipsis',
                }}
              >
                {val}
              </div>
            </div>
          );
        }
      }else if(item.dataIndex=="page"){
        item.render=(val,row,index)=>{
          let valArr=val?.split(',')[2]
          return (
            <div
            style={{
              lineHeight: '20px',
              width: 120,
              overflow: 'hidden',
              whiteSpace: 'nowrap',
              textOverflow: 'ellipsis',
            }}
          >
            {valArr}
          </div>
          )
        }
      }
    })
    if (viewType === 'card' && key === 'attrs') {
      columns = useFormatCardAttrColumns(
        columns,
        value,
        props.onChange,
        setExpandedRowKey,
        refObj[key],
      );
    }
    if (sourceType === 'api' && key === 'actions') {
      const blackList = [ActionEnum.add, ActionEnum.view, ActionEnum.edit];
      value.tableValues.actions.forEach((item: any, index: number) => {
        if (blackList.includes(item.actionType)) {
          value.tableValues.actions.splice(index, 1)
        }
      })
    }
    if (getPlatform() == 'web' && key === 'subWindow') {
      const actionList = refObj['actions'].current?.getDataSource?.() || [];
      const customActions = actionList.filter(action => action.actionType === ActionEnum.custom);
      if (customActions?.length) {
        customActions.forEach(item => {
          columns[0].editData.options.push({
            label: getMessage(item.actionName),
            value: item.operationflag
          })
        })
      }
    }
    return {
      newValue,
      config,
      add,
      columns,
      value,
    };
  };
  // 配置按钮事件
  const clickConfigBtn = useCallback(() => {
    // if (
    //   !(form.fields['form.senior.soure.x-component-props.sourceModel'] as unknown as Field)?.value
    // ) {
    //   message.warn(getMessage('table.tips.pleaseSelectTheQueryDataSourceFirst'));
    //   return;
    // }
    setVisible(true);
  }, [form]);

  const getAttrsConfig = validateRender('attrs');

  useEffect(() => {
    if (viewType === 'card' && !value.tableValues?.attrs) {
      //初始化默认模板表格数据
      initCardAttrs(tmplInfo, 'default');
    } else {
      initTableAttrs();
    }
  }, [viewType, fields, resizeField]);

  useEffect(() => {
    if (!form['appInfo']) {
      return;
    }
    getPageTree(form['appInfo']).then((res) => {
      if (res) {
        setPages(
          tileTree(res).map((item: any) => {
            return {
              value: `${item.Route},${item.OutId}`,
              label: item.DisplayName,
            };
          }),
        );
      }
    });
  }, [form['appInfo']]);

// 新建页面带表格的模板兼容（设置了按钮颜色，按钮图标跟随按钮颜色；未设置按钮颜色，按钮图标跟随主题色）
value?.tableValues?.actions?.map((item:any)=>{
  if(item?.icon?.color){
    delete item?.icon?.color
  }
  return item
})
  return (
    <>
      <Button type="primary" onClick={clickConfigBtn}>
        <TextWidget>table.columnConfig</TextWidget>
      </Button>
      <Modal
        wrapClassName={`${cls(prefixCls)}`}
        width={getPlatform() == 'wap' ? '760px' : '1142px'}
        visible={visible}
        title={getMessage('table.columnConfig')}
        okText={getMessage('table.sure')}
        cancelText={getMessage('table.cancel')}
        onOk={setData}
        onCancel={() => setVisible(false)}
        destroyOnClose
      >
        <TmplCtx.Provider value={{ tmplInfo, setTmplInfo, onSaveCardTmpl }}>
          {thumbnail ? (
            <>
              <FieldForm
                initialValues={{
                  ...getAttrsConfig.newValue,
                  auth: value?.auth,
                }}
                formItemsRef={formItemsRef}
                fields={getAttrsConfig.config.formItems}
                layout={getAttrsConfig.config.layout}
              />

              <EditableTable
                className={'editable-table'}
                rowKey={'id'}
                columns={getAttrsConfig.columns}
                dataSource={value?.tableValues?.['attrs']}
                rowSelection={{ columnWidth: 44 }}
                isRowSelection={false}
                addBtn={!getAttrsConfig.config.hideButton}
                deleteBtn={!getAttrsConfig.config.hideButton}
                disableDraggable={getAttrsConfig.config.hideButton}
                expandable={expandable(viewType, 'attrs')}
                onAdd={getAttrsConfig.add}
                ref={refObj['attrs']}
                scroll={{ y: 300 }}
              />
            </>
          ) : (
            <Tabs activeKey={activeKey} onChange={(key) => setActiveKey(key)}>
              {Object.keys(TabsConfig()).map((key) => {
                const { newValue, config, columns, add, value } = validateRender(key);
                return (
                  <Tabs.TabPane tab={config.name} key={key}>
                    <FieldForm
                      initialValues={{
                        ...newValue,
                        auth: value?.auth,
                      }}
                      formItemsRef={formItemsRef}
                      fields={config.formItems}
                      layout={config.layout}
                      otherFormItem={
                        key === 'actions' && (
                          <AuthForm
                            initialValues={props.value?.auth}
                            onChange={changeHandle}
                            withoutForm={true}
                          />
                        )
                      }
                    />

                    {!(sourceType === 'api' && key === 'subWindow') && (
                      <EditableTable
                        className={'editable-table'}
                        rowKey={'id'}
                        columns={columns}
                        dataSource={value?.tableValues?.[key]}
                        rowSelection={{ columnWidth: 44 }}
                        isRowSelection={viewType === 'card' && key === 'attrs' ? false : true}
                        addBtn={!config.hideButton}
                        deleteBtn={!config.hideButton}
                        disableDraggable={config.hideButton}
                        expandable={expandable(viewType, key)}
                        onAdd={add}
                        ref={refObj[key]}
                        scroll={{ y: 300 }}
                      />
                    )}
                  </Tabs.TabPane>
                );
              })}
            </Tabs>
          )}
        </TmplCtx.Provider>
      </Modal>
    </>
  );
};

export default React.memo(ColumnConfig);
